<template>
  <div class="v-upload">
    <el-upload
      :key="key"
      action="#"
      :http-request="httpRequest"
      :show-file-list="false"
      v-bind="$attrs"
      :class="props.classes"
      :multiple="props.multiple"
      :before-upload="beforeAvatarUpload"
    >
      <slot />
    </el-upload>
    <el-progress
      class="mt-1"
      v-if="props.progress && progressPercent"
      :percentage="progressPercent"
      :width="128"
    />
  </div>
</template>

<script setup>
import api from "./api";
import axios from "axios";
import MD5 from "spark-md5";
import { ElMessage } from "element-plus";
const props = defineProps({
  type: { type: String, default: "img" }, // 上传类型
  limit: { type: Number, default: 1 },
  classes: { type: String, default: "" }, // el-upload的class
  validator: { type: Function, default: () => {} }, // 校验函数
  progress: { type: Boolean, default: false }, // 是否使用进度条
  multiple: { type: Boolean, default: false }, //
  is_checkout: { type: Boolean, default: false }, //
  // drag
});
const emit = defineEmits(["success", "error"]);
const key = ref(0);
const progressPercent = ref(0);
watch(progressPercent, (val) => {
  if (val === 100) {
    const timer = setTimeout(() => {
      progressPercent.value = 0;
      clearTimeout(timer);
    }, 1000);
  }
});
const beforeUpload = (file) => {
  if (props.limit === 1) key.value++;
  return new Promise((resolve, reject) => {
    const { name, type, size } = file;
    const url = URL.createObjectURL(file);
    const types = {
      // 图片上传
      img: () => {
        let img = document.createElement("img");
        img.src = url;
        img.onload = () => {
          const { width, height } = img;
          const fileInfo = { width, height, size, name, type };
          // 校验
          const massge = props.validator && props.validator(fileInfo);
          img = null;
          massge && reject(massge);
          resolve(fileInfo);
        };
      },
      // 视频上传
      video: () => {
        let video = document.createElement("video");
        video.preload = "metadata";
        video.src = url;
        video.autoplay = true;
        video.onloadedmetadata = () => {
          const { duration, videoWidth: width, videoHeight: height } = video;
          const fileInfo = { width, height, size, name, type, time: Math.ceil(duration) };
          // 校验
          const massge = props.validator && props.validator(fileInfo);
          video = null;
          massge && reject(massge);
          resolve(fileInfo);
        };
      },
      // 文件上传
      file: () => {
        resolve();
      },
    };
    types[props.type]();
  });
};
const httpRequest = (fileData) => {
  const { file } = fileData;
  beforeUpload(file)
    .then((fileInfo) => {
      let formData = new FormData();
      formData.append("file", file);
      api[props.type === "img" ? "uploadImg" : "uploadFile"](
        formData,
        handleUploadProgress
      ).then((res) => {
        const spark = new MD5.ArrayBuffer();
        spark.append(file);
        const secret = spark.end(false);
        emit("success", { ...fileInfo, ...res.data, secret });
      });
    })
    .catch((e) => {
      emit("error", e);
    });
};

const handleUploadProgress = (event) => {
  if (event.lengthComputable) {
    progressPercent.value = (event.loaded / event.total).toFixed(2) * 100;
  }
};

const beforeAvatarUpload = (rawFile) => {
  if (!props.is_checkout) {
    return true;
  }
  if (!isImageType(rawFile.type)) {
    ElMessage.error("图片类型只能是jpg/png/jpeg/pdf");
    return false;
  } else if (rawFile.size / 1024 / 1024 > 5) {
    ElMessage.error("图片大小不能超过 5MB!");
    return false;
  }
  return true;
};

const isImageType = (filename) => {
  // 定义允许的图片类型的正则表达式
  const allowedExtensions = /^(image\/(png|jpeg|jpg)|application\/pdf)$/i;
  // 检查文件名是否以允许的图片类型结尾
  return allowedExtensions.test(filename);
};
</script>

<style lang="scss" scoped></style>
